﻿using UnityEngine;
using System;
using UniRx;

public partial class Timer
{
    /// <summary>
    /// 单线计时器，提供 开始、结束、更新、归一化事件
    /// </summary>
    public class SingleStage
    {
        /// <summary>
        /// 计时器开始
        /// </summary>
        public IObservable<Unit> onStart => onTimerStart;

        /// <summary>
        /// 计时器结束
        /// </summary>
        public IObservable<Unit> onFinish => onTimerEnd;

        /// <summary>
        /// 计时器被外部中断
        /// </summary>
        public IObservable<Unit> onShutDown => onShutdown;

        /// <summary>
        /// 计时器更新，已运行事件
        /// </summary>
        public IObservable<float> onUpdate => runTime;

        /// <summary>
        /// 进度归一化更新
        /// </summary>
        public IObservable<float> onNormalizedUpdate => runTimeNormalized;

        /// <summary>
        /// 计时器是否还在运行
        /// </summary>
        public bool isRuning => time > 0;

        private Subject<Unit> onTimerStart = new Subject<Unit>();
        private Subject<Unit> onTimerEnd = new Subject<Unit>();
        private Subject<Unit> onShutdown = new Subject<Unit>();
        private ReactiveProperty<float> runTime = new ReactiveProperty<float>();
        private ReactiveProperty<float> runTimeNormalized = new ReactiveProperty<float>();
        private IDisposable process = null;
        private float time = -1f;

        /// <summary>
        /// 开始计时，gameobject未激活时暂停计时
        /// </summary>
        public void Start(float countTime, MonoBehaviour owner = null)
        {
            time = 0f;
            // 计时开始
            onTimerStart.OnNext(Unit.Default);
            process?.Dispose();
            process = Observable.EveryLateUpdate().Where(_ => owner == null || owner.gameObject.activeInHierarchy).Subscribe(_ =>
            {
                if (time < 0)
                {
                    //释放掉计时线程
                    process.Dispose();
                }
                time += Time.deltaTime;
                // 更新计时
                runTime.Value = Mathf.Clamp(time, 0, countTime);
                // 更新计时归一化
                runTimeNormalized.Value = Mathf.Clamp(time / countTime, 0, countTime);
                if (time >= countTime)
                {
                    time = -1f;
                    //释放掉计时线程
                    process.Dispose();
                    // 计时结束
                    onTimerEnd.OnNext(Unit.Default);
                }
            });
        }

        /// <summary>
        /// 停止计时器
        /// </summary>
        public void ShutDown()
        {
            time = -1f;
            if (time > 0)
                onShutdown.OnNext(Unit.Default);
        }
    }
}